package excelrept

import (
	"fmt"
	"strings"

	"shqsoft.cn/pas3ui/base"
)

var dbTablePool map[string][]DBCloumn = make(map[string][]DBCloumn)

func getDBColumns(tableName string) (cols []DBCloumn, err error) {
	dbType := "clickhouse"
	var ok bool
	cols, ok = dbTablePool[tableName]
	if !ok {
		var db DataBase
		if dbType == "mysql" {
			db = &MySQL{}
		} else if dbType == "clickhouse" {
			db = &Clickhouse{}
		}
		cols, _, err = db.GetTableCloumns(tableName)
		if err != nil {
			return
		}
		dbTablePool[tableName] = cols
		return
	}
	return
}

//DBCloumn 数据库表字段
type DBCloumn struct {
	Name         string      `gorm:"column:列名"`
	Desc         string      `gorm:"column:列说明"`
	DataType     string      `gorm:"column:数据类型"`
	Length       int         `gorm:"column:长度"`
	Precision    int         `gorm:"column:小数位数"`
	IsPK         bool        `gorm:"column:主键"`
	IsNull       bool        `gorm:"column:允许空"`
	DefaultValue string      `gorm:"column:默认值"`
	IsIdentity   bool        `gorm:"column:标识"`
	convertFunc  ConvertFunc `gorm:"-"`
}

//DataBase 数据库访问接口
type DataBase interface {
	GetTableCloumns(string) ([]DBCloumn, string, error)
}

//Clickhouse Clickhouse数据库访问
type Clickhouse struct {
}

//GetTableCloumns 获取Clickhouse的指定表的
func (ss *Clickhouse) GetTableCloumns(tName string) ([]DBCloumn, string, error) {
	var cols []DBCloumn
	if err := base.CHDB.Raw(chSQL, tName).Scan(&cols).Error; err != nil {
		return nil, "", err
	}
	var pkey string
	for i := 0; i < len(cols); i++ {
		dtype := cols[i].DataType
		if strings.HasPrefix(dtype, "Int") || strings.HasPrefix(dtype, "UInt") {
			cols[i].convertFunc = Convert2Int
		} else if strings.HasPrefix(dtype, "Decimal") || dtype == "Float32" || dtype == "Float64" {
			cols[i].convertFunc = Convert2Float
		} else if dtype == "Date" || dtype == "Datetime" || dtype == "Datetime2" {
			cols[i].convertFunc = Convert2Date
		} else {
			cols[i].convertFunc = Convert2String
		}
	}
	return cols, pkey, nil
}

//MySQL MySQL数据库访问
type MySQL struct {
}

//GetTableCloumns 获取SQLServer的指定表的
func (ms *MySQL) GetTableCloumns(tName string) ([]DBCloumn, string, error) {
	var cols []DBCloumn
	if err := base.MYDB.Raw(mySQLSQL, tName).Scan(&cols).Error; err != nil {
		return nil, "", err
	}
	var pkey string
	pCount := 0
	for i := 0; i < len(cols); i++ {
		switch cols[i].DataType {
		case "int":
			cols[i].convertFunc = Convert2Int
		case "money", "decimal", "float", "numeric":
			cols[i].convertFunc = Convert2Float
		case "date", "datetime":
			cols[i].convertFunc = Convert2Date
		case "bit":
			cols[i].convertFunc = Convert2Bool
		default:
			cols[i].convertFunc = Convert2String
		}
	}
	if pCount > 1 {
		return nil, "", fmt.Errorf("表%s的主键有%d个，目前框架仅支持一个主键！", tName, pCount)
	}
	return cols, pkey, nil
}

const mySQLSQL string = `select COLUMN_NAME 列名,COLUMN_COMMENT 列说明,DATA_TYPE 数据类型,
IFNULL(CHARACTER_MAXIMUM_LENGTH,NUMERIC_PRECISION) 长度,NUMERIC_SCALE 小数位数,
CASE WHEN IS_NULLABLE='YES' THEN 1 ELSE 0 END 允许空,  默认值,
	  CASE WHEN COLUMN_KEY='PRI' THEN 1 ELSE 0 END 主键,
CASE WHEN EXTRA='auto_increment' THEN 1 ELSE 0 END 标识
from information_schema.COLUMNS where table_name = ?`

const chSQL string = "select name `列名`,comment `列说明`,type `数据类型`,is_in_primary_key `主键` from system.columns c where table = ?"
